﻿/*
 * Copyright (c) 2012 Lambert van Lieshout, YUMMO Software Development
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
*/

namespace Yummo.BlackBox
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;

    public class EventTSqlReader
    {
        private SqlConnection   _connection;
        private bool            _keepConnectionOpen;

        public EventTSqlReader(bool keepConnectionOpen, string connectionString)
        {
            if (String.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString");
            _keepConnectionOpen = keepConnectionOpen;
            _connection = new SqlConnection(connectionString);
        }

        /// <summary>
        /// Get event log items in database.
        /// </summary>
        /// <returns>Event log items in database.</returns>
        public int GetLogItemCount()
        {
            if (_connection.State == ConnectionState.Closed) _connection.Open();
            int count = 0;
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = _connection;
                command.CommandText = "SELECT COUNT(*) FROM [BlackBox]";
                object o = command.ExecuteScalar();
                if (o is int) count = (int)o;
                else throw new Exception("Result is not of type int.");
            }
            if (!_keepConnectionOpen) _connection.Close();
            return count;
        }

        /// <summary>
        /// Clean-up event log table and resets id counter. Returns rows removed.
        /// </summary>
        /// <returns>Rows remove count.</returns>
        public int Cleanup()
        {
            if (_connection.State == ConnectionState.Closed) _connection.Open();
            int rowsAffected = 0;
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = _connection;
                command.CommandText = "TRUNCATE TABLE [BlackBox]";
                rowsAffected = command.ExecuteNonQuery();
            }
            if (!_keepConnectionOpen) _connection.Close();
            return rowsAffected;
        }

        /// <summary>
        /// Retrieve event messages.
        /// </summary>
        /// <param name="count">Number of event messages to retrieve.</param>
        /// <returns>List of event messages.</returns>
        public List<EventMessage> Get(int count = int.MaxValue)
        {
            List<EventMessage> messages = new List<EventMessage>();
            if (_connection.State == ConnectionState.Closed) _connection.Open();
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = _connection;
                command.CommandText = "SELECT TOP (@ResultCount) [EventId],[EventType],[Host],[TimeStamp],[Service],[Parameters],[Data] FROM [BlackBox] ORDER BY [EventId] DESC";
                command.Parameters.Add("ResultCount", SqlDbType.Int).Value = count;
                using (SqlDataReader reader = command.ExecuteReader())
                    while (reader.Read())
                        messages.Add(Reader(reader));
            }
            if (!_keepConnectionOpen) _connection.Close();
            return messages;
        }

        private static EventMessage Reader(SqlDataReader reader)
        {
            EventMessage message = new EventMessage();
            message.EventId     = (long)reader["EventId"];
            message.EventType   = (EventTypes)reader["EventType"];
            message.Host        = (string)reader["Host"];
            message.TimeStamp   = (DateTime)reader["TimeStamp"];
            message.Service     = (string)reader["Service"];
            message.Data        = (string)reader["Data"];
            if (reader["Parameters"] != DBNull.Value) message.Parameters = (string)reader["Parameters"];
            return message;
        }
    }
}
